package com.wy.w_ui.tab.top;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.example.w_library.utils.DisplayUtil;
import com.wy.w_ui.tab.bottom.WTabBottomInfo;
import com.wy.w_ui.tab.common.IWTabLayout;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class WTabTopLayout extends HorizontalScrollView implements IWTabLayout<WTabTop, WTabTopInfo<?>> {

    private List<OnTabSelectListener<WTabTopInfo<?>>> tabSelectChangeListeners = new ArrayList<>();
    private WTabTopInfo<?> selectedInfo;
    private List<WTabTopInfo<?>> infoList;
    //tab 宽度
    private int tabWith;

    public WTabTopLayout(Context context) {
        this(context,null);
    }

    public WTabTopLayout(Context context, AttributeSet attrs) {
        this(context,attrs,0);
    }

    public WTabTopLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        setVerticalScrollBarEnabled(false);
    }


    @Override
    public WTabTop findTab(@NotNull WTabTopInfo<?> wTabTopInfo) {

        ViewGroup group = getRootLayout(false);

        for (int i = 0; i < group.getChildCount(); i++) {

            View child = group.getChildAt(i);
            if (child instanceof WTabTop){
                WTabTop tab = (WTabTop) child;
                if (tab.getTabTopInfo() == wTabTopInfo){
                    return tab;
                }
            }
        }
        return null;
    }

    @Override
    public void addTabSelectChangeListener(OnTabSelectListener<WTabTopInfo<?>> selectListener) {
        tabSelectChangeListeners.add(selectListener);
    }

    @Override
    public void defaultSelected(@NotNull WTabTopInfo<?> defaultInfo) {
        onSelected(defaultInfo);
    }

    @Override
    public void inflateInfo(@NotNull List<WTabTopInfo<?>> infoList) {

        if (infoList.isEmpty()){
            return;
        }

        this.infoList = infoList;

        LinearLayout rootLayout = getRootLayout(true);

        selectedInfo = null;

        Iterator<OnTabSelectListener<WTabTopInfo<?>>> iterator = tabSelectChangeListeners.iterator();
        while (iterator.hasNext()){
            if (iterator.next() instanceof WTabTop){
                iterator.remove();
            }
        }

        //创建tab
        for (final WTabTopInfo<?> wTabTopInfo : infoList) {
            WTabTop tabTop = new WTabTop(getContext());
            tabSelectChangeListeners.add(tabTop);
            tabTop.setTabInfo(wTabTopInfo);
            rootLayout.addView(tabTop);

            tabTop.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onSelected(wTabTopInfo);
                }
            });


        }


    }

    /**
     * 获取 tab 容器
     * @return
     */
    private LinearLayout getRootLayout(boolean clear){
        LinearLayout rootView = (LinearLayout) getChildAt(0);

        if (rootView == null){
            rootView = new LinearLayout(getContext());
            rootView.setOrientation(LinearLayout.HORIZONTAL);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            addView(rootView,layoutParams);
        }else {
            if (clear){
                rootView.removeAllViews();
            }
        }

        return rootView;
    }


    /**
     * tab 被点击
     * @param nextInfo 当前点击的 Tab
     */
    private void onSelected(WTabTopInfo<?> nextInfo){
        //遍历监听对象,挨个执行
        for (OnTabSelectListener<WTabTopInfo<?>> listener : tabSelectChangeListeners) {
            listener.onTabSelectChange(infoList.indexOf(nextInfo),selectedInfo,nextInfo);
        }

        selectedInfo = nextInfo;

        autoScroll(nextInfo);
    }

    /**
     * 自动滚动,点击自动滚动展示前后两个
     * @param nextTabInfo
     */
    private void autoScroll(WTabTopInfo<?> nextTabInfo){
        WTabTop tabTop  = findTab(nextTabInfo);
        if (tabTop == null) {
            return;
        }

        int index = infoList.indexOf(nextTabInfo);
        int[] loc = new int[2];
        //获取点击的控件在屏幕上的位置
        tabTop.getLocationInWindow(loc);
        int scrollWidth;
        if (tabWith == 0){
            tabWith = tabTop.getWidth();
        }

        //判断点击了屏幕的左侧还是右侧
        if (loc[0] + (tabWith /2) > DisplayUtil.deviceWidth(getContext()) /2){
            //向右滚动
            scrollWidth = rangeScrollWidth(index,2);
        }else {
            //向左滚动
            scrollWidth = rangeScrollWidth(index,-2);
        }

        scrollTo(getScrollX() + scrollWidth,0);

    }

    /**
     * 获取可滚动的范围
     * @param index 从第几个开始-点击控件的位置
     * @param range  向左还是向右滚动的个数 左负右正
     * @return scrollWidth
     */
    private int rangeScrollWidth(int index,int range){

        int scrollWidth = 0;
        for (int i = 0; i < Math.abs(range); i++) {
            int next;
            boolean toRight = range > 0;
            if (toRight){
                next = range - i + index;
            }else {
                next = range + i + index;
            }

            if (next > 0 && next < infoList.size()){
                if (toRight){
                    scrollWidth += scrollWidth(next,true);
                }else {
                    scrollWidth -= scrollWidth(next,false);
                }
            }
        }

        return scrollWidth;
    }

    /**
     * 指定位置控件需要滚动的距离
     * @param index 指定位置的控件
     * @param toRight 是否点击屏幕右侧
     * @return
     */
    private int scrollWidth(int index,boolean toRight){
        WTabTop targetTab = findTab(infoList.get(index));
        if (targetTab == null){
            return 0;
        }

        Rect rect = new Rect();
        //获取视图可见位置的坐标
        targetTab.getLocalVisibleRect(rect);

        if (toRight){
            if (rect.right > tabWith){
                //right坐标大于控件的宽度时,说明完全没有显示
                return tabWith;
            }else {
                //显示一部分,减去已显示的宽度
                return tabWith - rect.right;
            }
        }else {

            if (rect.left <= -tabWith){
                //left坐标小于等于 -控件的宽度,说明完全没有显示
                return tabWith;

            }else if (rect.left > 0){
                //显示一部分
                return rect.left;
            }

            return 0;
        }
    }
}
